home *** CD-ROM | disk | FTP | other *** search
- LISTING 27 - A Vector class template that manages its own heap
- #include <iostream.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <new.h>
-
- // Borland's <new.h> doesn't supply this:
- inline void *operator new(size_t, void *p)
- {
- return p;
- }
-
- // The next two are just for tracing execution:
- inline void *operator new(size_t siz)
- {
- cout << ">>> operator new (" << siz << " bytes)" << endl;
- return malloc(siz);
- }
-
- inline void operator delete(void *p)
- {
- cout << ">>> operator delete: " << (void *) p << endl;
- free(p);
- }
-
- template<class T>
- class Vector
- {
- public:
- Vector();
- Vector(size_t);
- ~Vector();
-
- // Append & subscript:
- Vector<T>& operator+=(const T&);
- T& operator[](size_t);
-
- // Length-related functions:
- size_t length() const;
- void resize(size_t);
- size_t capacity() const;
- void reserve(size_t);
-
- private:
- T *arena; // class-specific storage arena
- size_t length_;
- size_t capacity_;
-
- enum {CHUNK = 10};
-
- // Disallow copy and assign:
- Vector(const Vector&);
- Vector<T>& operator=(const Vector<T>&);
-
- static size_t next_chunk(size_t n);
- };
-
- template<class T>
- inline Vector<T>::Vector()
- {
- // Intialize an empty vector
- arena = 0;
- length_ = capacity_ = 0;
- }
-
- template<class T>
- inline Vector<T>::Vector(size_t n)
- {
- // Allocate a multiple of CHUNK elements >= n
- length_ = 0;
- capacity_ = next_chunk(n);
- arena = (T *) ::operator new(sizeof(T) * capacity_);
- cout << ">>> arena created at " << (void *) arena << endl;
- }
-
- template<class T>
- Vector<T>::~Vector()
- {
- // Execute destructor for each element
- for (int i = 0; i < length_; ++i)
- (arena+i)->T::~T();
-
- ::operator delete(arena);
- }
-
- template<class T>
- inline T& Vector<T>::operator[](size_t pos)
- {
- if (pos >= length_)
- throw "bad index in Vector<T>::operator[]";
- return arena[pos];
- }
-
- template<class T>
- inline size_t Vector<T>::length() const
- {
- return length_;
- }
-
- template<class T>
- inline size_t Vector<T>::capacity() const
- {
- return capacity_;
- }
-
- template<class T>
- void Vector<T>::reserve(size_t new_capacity)
- {
- // Only allow an increase:
- if (new_capacity > capacity_)
- {
- new_capacity = next_chunk(new_capacity);
- if (new_capacity > capacity_)
- {
- // Copy elements to new space
- T *new_arena = (T*) ::operator new(sizeof(T) *
- new_capacity);
- cout << ">>> new arena created at "
- << (void *) new_arena << endl;
- for (int i = 0; i < length_; ++i)
- (void) new (new_arena + i) T(arena[i]);
-
- // Destroy old vector
- for (i = 0; i < length_; ++i)
- (arena+i)->T::~T();
- delete arena;
-
- // Update state
- arena = new_arena;
- capacity_ = new_capacity;
- }
- }
- }
-
- template<class T>
- void Vector<T>::resize(size_t new_length)
- {
- // Only allow a decrease:
- if (new_length < length_)
- {
- // Just destroy truncated elements;
- // Don't change capacity
- for (int i = new_length; i < length_; ++i)
- (arena+i)->T::~T();
- length_ = new_length;
- }
- }
-
- template<class T>
- Vector<T>& Vector<T>::operator+=(const T& x)
- {
- if (length_ == capacity_)
- reserve(length_ + 1);
- (void) new (arena + length_++) T(x);
- return *this;
- }
-
- template<class T>
- inline size_t Vector<T>::next_chunk(size_t n)
- {
- return ((n + CHUNK - 1) / CHUNK) * CHUNK;
- }
-